// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) definits fieldsfirst ansi space safe 
// Source File Name:   RigidWorld.java

package jones.rigid;

import java.io.PrintStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import jones.SimObject;
import jones.SimpleRobot;

// Referenced classes of package jones.rigid:
//            ConvexPolygon, RigidBody, OverlappingRigidBodyException

public class RigidWorld
    implements SimObject, Serializable
{

    private List rigidBodies = null;
    private List collisionGraph = null;
    private List colliding = null;
    private List pushing = null;
    private ConvexPolygon shape1 = null;
    private ConvexPolygon shape2 = null;

    public RigidWorld()
    {
        rigidBodies = ((List) (new ArrayList()));
        collisionGraph = ((List) (new ArrayList()));
        colliding = ((List) (new ArrayList()));
        pushing = ((List) (new ArrayList()));
        shape1 = new ConvexPolygon();
        shape2 = new ConvexPolygon();
    }

    public void add(RigidBody body)
        throws OverlappingRigidBodyException
    {
        for (int i = 0; i < rigidBodies.size(); i++)
            if (isColliding((RigidBody)rigidBodies.get(i), body))
                throw new OverlappingRigidBodyException();

        rigidBodies.add(((Object) (body)));
        collisionGraph.add(((Object) (new ArrayList())));
    }

    public void remove(RigidBody body)
    {
        int index = rigidBodies.indexOf(((Object) (body)));
        rigidBodies.remove(((Object) (body)));
        collisionGraph.remove(index);
    }

    public void update(double time)
    {
        if (!createCollisionGraph())
            throw new RuntimeException("Colliding bodies at start of rigid world update!");
        for (int i = 0; i < rigidBodies.size(); i++)
        {
            RigidBody body = (RigidBody)rigidBodies.get(i);
            body.move(time);
        }

        pushing.clear();
        colliding.clear();
        createCollisionGraph();
        for (int i = 0; i < rigidBodies.size(); i++)
        {
            RigidBody body = (RigidBody)rigidBodies.get(i);
            List neighbors = (List)collisionGraph.get(i);
            if (neighbors.size() == 1)
            {
                RigidBody neighbor = (RigidBody)neighbors.get(0);
                if (neighbor.isPushable())
                {
                    neighbors = (List)collisionGraph.get(rigidBodies.indexOf(((Object) (neighbor))));
                    if (neighbors.size() == 1)
                    {
                        neighbor.push(body, time);
                        if (isColliding(body, neighbor))
                        {
                            System.out.println("*** Objects are still colliding after push ***!");
                            if (neighbor instanceof SimpleRobot)
                            {
                                SimpleRobot robot = (SimpleRobot)neighbor;
                                System.out.println("Robot in state " + robot.getLastChosenBehavior());
                            }
                        }
                        pushing.add(((Object) (body)));
                    }
                }
            }
        }

        for (boolean isProgressing = true; !createCollisionGraph() && isProgressing;)
        {
            isProgressing = false;
            for (int i = 0; i < rigidBodies.size(); i++)
            {
                RigidBody body = (RigidBody)rigidBodies.get(i);
                List neighbors = (List)collisionGraph.get(i);
                if (!neighbors.isEmpty())
                {
                    body.revert();
                    colliding.add(((Object) (body)));
                    pushing.remove(((Object) (body)));
                    isProgressing = true;
                }
            }

        }

    }

    public boolean createCollisionGraph()
    {
        boolean isDone = true;
        for (int i = 0; i < collisionGraph.size(); i++)
        {
            List neighbors = (List)collisionGraph.get(i);
            neighbors.clear();
        }

        for (int i = 0; i < rigidBodies.size(); i++)
        {
            RigidBody body1 = (RigidBody)rigidBodies.get(i);
            for (int j = 0; j < rigidBodies.size(); j++)
            {
                RigidBody body2 = (RigidBody)rigidBodies.get(j);
                if (isColliding(body1, body2))
                {
                    List neighbors = (List)collisionGraph.get(i);
                    neighbors.add(((Object) (body2)));
                    isDone = false;
                }
            }

        }

        return isDone;
    }

    private boolean isColliding(RigidBody body1, RigidBody body2)
    {
        if (((Object) (body1)).equals(((Object) (body2))))
        {
            return false;
        } else
        {
            body1.getCurrentShape(shape1);
            body2.getCurrentShape(shape2);
            return shape1.intersects(shape2);
        }
    }

    public boolean intersects(ConvexPolygon p)
    {
        for (int i = 0; i < rigidBodies.size(); i++)
        {
            RigidBody body = (RigidBody)rigidBodies.get(i);
            body.getCurrentShape(shape1);
            if (shape1.intersects(p))
                return true;
        }

        return false;
    }

    public boolean intersects(double x1, double y1, double x2, double y2)
    {
        for (int i = 0; i < rigidBodies.size(); i++)
        {
            RigidBody body = (RigidBody)rigidBodies.get(i);
            body.getCurrentShape(shape1);
            if (shape1.intersects(x1, y1, x2, y2))
                return true;
        }

        return false;
    }

    public boolean isColliding(RigidBody body)
    {
        return colliding.contains(((Object) (body)));
    }

    public boolean isPushing(RigidBody body)
    {
        return pushing.contains(((Object) (body)));
    }
}
